package com.example.blackmarket.utils;

import android.os.Handler;
import android.util.Log;


import com.example.blackmarket.entities.JsonWebToken;
import com.example.blackmarket.entities.UploadResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


public class OkHttpClientUtil {
    private static OkHttpClientUtil okHttpClientUtilInstance;
    private OkHttpClient mOkHttpClient;
    private Handler mHandler = new Handler();

    /**
     * 单例模式创建单实例
     * @return okHttpClientUtilInstance
     */
    public static OkHttpClientUtil getInstance(){
        if (okHttpClientUtilInstance == null){
            synchronized (OkHttpClientUtil.class) {
                if (okHttpClientUtilInstance == null) {
                    okHttpClientUtilInstance = new OkHttpClientUtil();
                }
            }
        }
        return okHttpClientUtilInstance;
    }

    private OkHttpClientUtil(){
        mOkHttpClient = (new OkHttpClient()).newBuilder()
                .addInterceptor(new TokenInterceptor())
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();
    }

    /**
     *
     * @param url url
     * @param callback
     * 如果请求成功则回调onSuccess，注意回调传入的data是 response.body().string();，请在presenter做gson解析
     * 请求失败则回调onError
     */
    public void GET(String url, Callback callback){
        Call call;
        try{
            Request request= buildRequestForGet(url);
            call = mOkHttpClient.newCall(request);
            if(callback!=null)
                call.enqueue(callback);
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     *
     * @param url url
     * @param callback
     * @param headersParams POST请求头，无需要则赋 null
     * @param params POST body 可接受参数类型有Map<String, String>，JsonObject，String，null
     */
    public void POST(String url, Callback callback, Map<String,String> headersParams, Object params){
        Call call;Request request = null;
        try{
            if (params instanceof Map) {
                request = buildRequestForPost(url, headersParams, (Map<String, String>) params);
            }
            else if (params instanceof JsonObject){
                request = buildRequestForPost(url,headersParams, (JsonObject) params);
            }
            else{
                request = buildRequestForPost(url,headersParams,(String) params);
            }
            call = mOkHttpClient.newCall(request);
            if(callback!=null)
                call.enqueue(callback);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 同步登录获取token，如果在主线程调用需要放入子线程中执行
     * 如果届时登录信息存入到body中则添加一个参数
     * @param url
     * @return
     */
    public Response syncLogin(String url) throws IOException {
        Request request = buildRequestForPost(url,null, (Map<String, String>) null);
        Call call=mOkHttpClient.newCall(request);
        return call.execute();
    }

    /**
     * 同步请求上传文件
     * @param url
     * @param filePath
     * @return 文件在服务器保存的url
     */
    public String syncPostFile(String url, String filePath) throws IOException {

        //开线程异步获取String
        ExecutorService pool = Executors.newSingleThreadExecutor();

        Future<String> future = pool.submit(() -> {
            File file = new File(filePath);
            if (file.exists()) {
                Log.d("111", "文件存在");
            }
            MultipartBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("image",file.getName(),
                            RequestBody.create(MediaType.parse("multipart/form-data"), file))
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();

            Call call = mOkHttpClient.newCall(request);
            Response response = call.execute();
                String responseResult = response.body().string();
                Gson gson = new Gson();
                UploadResponse uploadResponse = gson.fromJson(responseResult, UploadResponse.class);
                return uploadResponse.getUrl();
        });
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            String pictureUrl = future.get();
            return pictureUrl;
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Request buildRequestForGet(String url){

        return new Request.Builder()
                .url(url)
                .get()
                .build();
    }

    private Request buildRequestForPost(String url, Map<String,String> headersParams, String body){
        RequestBody requestBodyJson=RequestBody.create(MediaType.parse("application/json;charset=utf-8"), body!=null?body:"");
        return new Request.Builder()
                .url(url)
                .headers(getRequestHeaders(headersParams))
                .post(requestBodyJson)
                .build();
    }

    private Request buildRequestForPost(String url, Map<String,String> headersParams, Map<String, String> params){
        FormBody.Builder builder = new FormBody.Builder();
        if (params!=null){
            for (Map.Entry<String,String>entry : params.entrySet()){
                builder.add(entry.getKey(),entry.getValue());
            }
        }
        FormBody formBody = builder.build();

        return new Request.Builder()
                .headers(getRequestHeaders(headersParams))
                .url(url)
                .post(formBody)
                .build();
    }

    private Request buildRequestForPost(String url, Map<String,String> headersParams, JsonObject jsonObject){
        String jsonStr = "";
        if (jsonObject!=null)
            jsonStr=jsonObject.toString();
        //创建requestBody,并把jsonStr封装进去
        RequestBody requestBodyJson=RequestBody.create(MediaType.parse("application/json;charset=utf-8"),jsonStr);
        return new Request.Builder()
                .url(url)
                .headers(getRequestHeaders(headersParams))
                .post(requestBodyJson)
                .build();
    }



    /**
     * 添加请求头
     * @param headersParams
     * @return headers
     */
    private Headers getRequestHeaders(Map<String,String> headersParams){
        Headers headers;
        Headers.Builder builder = new Headers.Builder();
        if (headersParams != null){
            for (String key : headersParams.keySet()) {
                builder.add(key, Objects.requireNonNull(headersParams.get(key)));
            }
        }
        headers = builder.build();
        return headers;
    }

}
